package com.king.modules.system.service.impl;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.validation.Validator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.king.common.constant.UserConstants;
import com.king.common.exception.AssertHelper;
import com.king.common.utils.SecurityUtils;
import com.king.common.utils.bean.BeanValidators;
import com.king.common.utils.sign.Md5Utils;
import com.king.common.utils.spring.SpringUtils;
import com.king.common.utils.text.StringUtils;
import com.king.framework.base.service.impl.YyBaseServiceImpl;
import com.king.modules.system.domain.SysOrgEntity;
import com.king.modules.system.domain.SysRoleEntity;
import com.king.modules.system.domain.SysUserEntity;
import com.king.modules.system.domain.SysUserRoleEntity;
import com.king.modules.system.mapper.SysUserMapper;
import com.king.modules.system.service.SysConfigService;
import com.king.modules.system.service.SysOrgService;
import com.king.modules.system.service.SysRoleService;
import com.king.modules.system.service.SysUserRoleService;
import com.king.modules.system.service.SysUserService;

/**
 * 用户 业务层处理
 * 
 * @author king
 */
@Service
public class SysUserServiceImpl extends YyBaseServiceImpl<SysUserMapper, SysUserEntity, Long> implements SysUserService {

	private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);

	@Autowired
	private SysUserMapper userMapper;
	@Autowired
	private SysRoleService roleService;
	@Autowired
	private SysUserRoleService userRoleService;
	@Autowired
	private SysConfigService configService;
	@Autowired
	private SysOrgService orgService;
	@Autowired
	protected Validator validator;
	@Autowired
	private SysConfigService sysConfigService;

	@Override
	public void beforeAdd(SysUserEntity entity) throws Exception {
		AssertHelper.getInstance().checkException(UserConstants.NOT_UNIQUE.equals(checkUserNameUnique(entity)), 
				"新增用户'" + entity.getUserName() + "'失败，登录账号已存在");
		AssertHelper.getInstance().checkException(StringUtils.isNotEmpty(entity.getPhonenumber())
				&& UserConstants.NOT_UNIQUE.equals(checkPhoneUnique(entity)), 
				"新增用户'" + entity.getUserName() + "'失败，手机号码已存在");
		AssertHelper.getInstance().checkException(StringUtils.isNotEmpty(entity.getEmail())
				&& UserConstants.NOT_UNIQUE.equals(checkEmailUnique(entity)), 
				"新增用户'" + entity.getUserName() + "'失败，邮箱账号已存在");
		entity.setPassword(SecurityUtils.encryptPassword(Md5Utils.hash(sysConfigService.selectConfigByKey("sys.user.initPassword"))));
		
		SysOrgEntity org = orgService.findByPK(entity.getOrgid());
		entity.setGroupid(org.getGroupid());
		super.beforeAdd(entity);
	}

	@Override
	public void beforeUpdate(SysUserEntity oldEntity, SysUserEntity entity) throws Exception {
		AssertHelper.getInstance().checkException(UserConstants.NOT_UNIQUE.equals(checkUserNameUnique(entity)), 
				"修改用户'" + entity.getUserName() + "'失败，登录账号已存在");
		AssertHelper.getInstance().checkException(StringUtils.isNotEmpty(entity.getPhonenumber())
				&& UserConstants.NOT_UNIQUE.equals(checkPhoneUnique(entity)), 
				"修改用户'" + entity.getUserName() + "'失败，手机号码已存在");
		AssertHelper.getInstance().checkException(StringUtils.isNotEmpty(entity.getEmail())
				&& UserConstants.NOT_UNIQUE.equals(checkEmailUnique(entity)), 
				"修改用户'" + entity.getUserName() + "'失败，邮箱账号已存在");
		
		SysOrgEntity org = orgService.findByPK(entity.getOrgid());
		entity.setGroupid(org.getGroupid());
		super.beforeUpdate(oldEntity, entity);
	}

	/**
	 * 根据条件分页查询用户列表
	 * 
	 * @param user
	 *            用户信息
	 * @return 用户信息集合信息
	 */
	@Override
	public List<SysUserEntity> selectUserList(SysUserEntity user) {
		return userMapper.selectUserList(user);
	}

	/**
	 * 根据条件分页查询已分配用户角色列表
	 * 
	 * @param user
	 *            用户信息
	 * @return 用户信息集合信息
	 */
	@Override
	public List<SysUserEntity> inSelectRoleUsers(SysUserEntity user) {
		if (!SecurityUtils.isAdmin()) {
			user.setGroupid(SecurityUtils.getGroupid());
		}
		return userMapper.inSelectRoleUsers(user);
	}

	/**
	 * 根据条件分页查询未分配用户角色列表
	 * 
	 * @param user
	 *            用户信息
	 * @return 用户信息集合信息
	 */
	@Override
	public List<SysUserEntity> unSelectRoleUsers(SysUserEntity user) {
		if (!SecurityUtils.isAdmin()) {
			user.setGroupid(SecurityUtils.getGroupid());
		}
		return userMapper.unSelectRoleUsers(user);
	}
	
	
	@Override
	public List<SysUserEntity> inSelectProcessUsers(SysUserEntity user) {
		if (!SecurityUtils.isAdmin()) {
			user.setGroupid(SecurityUtils.getGroupid());
		}
		return userMapper.inSelectProcessUsers(user);
	}

	@Override
	public List<SysUserEntity> unSelectProcessUsers(SysUserEntity user) {
		if (!SecurityUtils.isAdmin()) {
			user.setGroupid(SecurityUtils.getGroupid());
		}
		return userMapper.unSelectProcessUsers(user);
	}
	
	

	/**
	 * 通过用户名查询用户
	 * 
	 * @param userName
	 *            用户名
	 * @return 用户对象信息
	 */
	@Override
	public SysUserEntity selectUserByUserName(String userName) {
		return userMapper.selectUserByUserName(userName);
	}

	/**
	 * 通过用户ID查询用户
	 * 
	 * @param userId
	 *            用户ID
	 * @return 用户对象信息
	 */
	@Override
	public SysUserEntity selectUserById(Long userId) {
		return userMapper.selectUserById(userId);
	}

	/**
	 * 查询用户所属角色组
	 * 
	 * @param userName
	 *            用户名
	 * @return 结果
	 */
	@Override
	public String selectUserRoles(Long userId) {
		List<SysRoleEntity> list = roleService.selectRolesByUserId(userId);
		if (CollectionUtils.isEmpty(list)) {
			return StringUtils.EMPTY;
		}
		return list.stream().map(SysRoleEntity::getRoleName).collect(Collectors.joining(","));
	}


	/**
	 * 校验用户名称是否唯一
	 * 
	 * @param user
	 *            用户信息
	 * @return 结果
	 */
	@Override
	public String checkUserNameUnique(SysUserEntity user) {
		Long userId = StringUtils.isNull(user.getId()) ? -1L : user.getId();
		SysUserEntity info = userMapper.checkUserNameUnique(user.getUserName());
		if (StringUtils.isNotNull(info) && info.getId().longValue() != userId.longValue()) {
			return UserConstants.NOT_UNIQUE;
		}
		return UserConstants.UNIQUE;
	}

	/**
	 * 校验手机号码是否唯一
	 *
	 * @param user
	 *            用户信息
	 * @return
	 */
	@Override
	public String checkPhoneUnique(SysUserEntity user) {
		Long userId = StringUtils.isNull(user.getId()) ? -1L : user.getId();
		SysUserEntity info = userMapper.checkPhoneUnique(user.getPhonenumber());
		if (StringUtils.isNotNull(info) && info.getId().longValue() != userId.longValue()) {
			return UserConstants.NOT_UNIQUE;
		}
		return UserConstants.UNIQUE;
	}

	/**
	 * 校验email是否唯一
	 *
	 * @param user
	 *            用户信息
	 * @return
	 */
	@Override
	public String checkEmailUnique(SysUserEntity user) {
		Long userId = StringUtils.isNull(user.getId()) ? -1L : user.getId();
		SysUserEntity info = userMapper.checkEmailUnique(user.getEmail());
		if (StringUtils.isNotNull(info) && info.getId().longValue() != userId.longValue()) {
			return UserConstants.NOT_UNIQUE;
		}
		return UserConstants.UNIQUE;
	}

	/**
	 * 校验用户是否允许操作
	 * 
	 * @param user
	 *            用户信息
	 */
	@Override
	public void checkUserAllowed(SysUserEntity user) {
		if (StringUtils.isNotNull(user.getId()) && user.isAdmin()) {
			AssertHelper.getInstance().throwException("不允许操作超级管理员用户");
		}
	}

	/**
	 * 校验用户是否有数据权限
	 * 
	 * @param userId
	 *            用户id
	 */
	@Override
	public void checkUserDataScope(Long userId) {
		if (!SysUserEntity.isAdmin(SecurityUtils.getUserId())) {
			SysUserEntity user = new SysUserEntity();
			user.setId(userId);
			List<SysUserEntity> users = SpringUtils.getAopProxy(this).selectUserList(user);
			if (StringUtils.isEmpty(users)) {
				AssertHelper.getInstance().throwException("没有权限访问用户数据！");
			}
		}
	}


	/**
	 * 修改用户状态
	 * 
	 * @param user
	 *            用户信息
	 * @return 结果
	 */
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	@Override
	public int updateUserStatus(SysUserEntity user) {
		return userMapper.updateUser(user);
	}

	/**
	 * 修改用户基本信息
	 * 
	 * @param user
	 *            用户信息
	 * @return 结果
	 */

	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	@Override
	public int updateUserProfile(SysUserEntity user) {
		return userMapper.updateUser(user);
	}

	/**
	 * 修改用户头像
	 * 
	 * @param userName
	 *            用户名
	 * @param avatar
	 *            头像地址
	 * @return 结果
	 */
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	@Override
	public boolean updateUserAvatar(Long id, String avatar) {
		return userMapper.updateUserAvatar(id, avatar) > 0;
	}

	/**
	 * 修改用户密码
	 * 
	 * @param user
	 *            用户信息
	 * @return 结果
	 */
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	@Override
	public int updateUserPwd(Long id, Long mr, String password) {
		return userMapper.updateUserPwd(id, mr, password);
	}

	/**
	 * 通过用户ID删除用户
	 * 
	 * @param userId
	 *            用户ID
	 * @return 结果
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public int deleteUserById(Long userId) {
		// 删除用户与角色关联
		userRoleService.deleteUserRoleByUserId(userId);
		return userMapper.deleteUserById(userId);
	}

	/**
	 * 批量删除用户信息
	 * 
	 * @param userIds
	 *            需要删除的用户ID
	 * @return 结果
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	public int deleteUserByIds(Long[] userIds) {
		for (Long userId : userIds) {
			checkUserAllowed(new SysUserEntity(userId));
			checkUserDataScope(userId);
		}
		// 删除用户与角色关联
		userRoleService.deleteUserRoleByUserIds(userIds);
		return userMapper.deleteUserByIds(userIds);
	}

	/**
	 * 导入用户数据
	 * 
	 * @param userList
	 *            用户数据列表
	 * @param isUpdateSupport
	 *            是否更新支持，如果已存在，则进行更新数据
	 * @param operName
	 *            操作用户
	 * @return 结果
	 */
	@Transactional(readOnly = false, rollbackFor = { Exception.class })
	@Override
	public String importUser(List<SysUserEntity> userList, Boolean isUpdateSupport, Long operUserId) {
		if (StringUtils.isNull(userList) || userList.size() == 0) {
			AssertHelper.getInstance().throwException("导入用户数据不能为空！");
		}
		int successNum = 0;
		int failureNum = 0;
		StringBuilder successMsg = new StringBuilder();
		StringBuilder failureMsg = new StringBuilder();
		String password = configService.selectConfigByKey("sys.user.initPassword");
		for (SysUserEntity user : userList) {
			try {
				// 验证是否存在这个用户
				SysUserEntity u = userMapper.selectUserByUserName(user.getUserName());
				if (StringUtils.isNull(u)) {
					BeanValidators.validateWithException(validator, user);
					user.setPassword(SecurityUtils.encryptPassword(password));
					user.setCr(operUserId);
					doAdd(user);
					successNum++;
					successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
				} else if (isUpdateSupport) {
					BeanValidators.validateWithException(validator, user);
					checkUserAllowed(user);
					checkUserDataScope(user.getId());
					user.setMr(operUserId);
					doUpdate(user);
					successNum++;
					successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
				} else {
					failureNum++;
					failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
				}
			} catch (Exception e) {
				failureNum++;
				String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败：";
				failureMsg.append(msg + e.getMessage());
				log.error(msg, e);
			}
		}
		if (failureNum > 0) {
			failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
			AssertHelper.getInstance().throwException(failureMsg.toString());
		} else {
			successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
		}
		return successMsg.toString();
	}

	@Override
	protected void processData(List<SysUserEntity> list) throws Exception {
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		Set<Long> orgIds = list.stream().map(SysUserEntity::getOrgid).collect(Collectors.toSet());
		List<SysOrgEntity> orgList = (List<SysOrgEntity>) orgService.findByPKS(orgIds);
		Map<Long, SysOrgEntity> orgMap = orgList.stream().collect(Collectors.toMap(obj -> obj.getId(), Function.identity()));
		SysOrgEntity org = null;
		for (SysUserEntity user : list) {
			org = orgMap.get(user.getOrgid());
			if (org == null) {
				continue;
			}
			user.setOrgName(org.getNodename());
		}
		super.processData(list);
	}

	@Override
	public List<SysRoleEntity> unSelectRoles(SysUserRoleEntity userRole) {
		if (!SecurityUtils.isAdmin()) {
			userRole.setGroupid(SecurityUtils.getGroupid());
		}
		return userMapper.unSelectRoles(userRole);
	}

	@Override
	public List<SysRoleEntity> inSelectRoles(SysUserRoleEntity userRole) {
		if (!SecurityUtils.isAdmin()) {
			userRole.setGroupid(SecurityUtils.getGroupid());
		}
		return userMapper.inSelectRoles(userRole);
	}
	
	@Transactional
	@Override
	public int deleteAuthRoles(Long userId, Long[] roleIds) {
		return userRoleService.deleteAuthRoles(userId, roleIds);
	}
	
	@Transactional
	@Override
	public int insertAuthRoles(Long userId, Long[] roleIds) {
		return userRoleService.insertAuthRoles(userId, roleIds);
	}

	

}
